package com.yehebl.orm.data.mysql;

import com.yehebl.orm.config.IConfig;
import com.yehebl.orm.data.common.*;
import com.yehebl.orm.data.common.dto.ExpressResult;
import com.yehebl.orm.data.common.dto.Page;
import com.yehebl.orm.data.common.dto.ResultObject;
import com.yehebl.orm.data.common.dto.SimplePage;
import com.yehebl.orm.data.common.xml.AQueryXmlSql;
import com.yehebl.orm.data.common.xml.QueryXmlSql;
import com.yehebl.orm.data.common.xml.dto.XmlSql;
import com.yehebl.orm.data.common.xml.manager.XmlSqlManager;
import com.yehebl.orm.data.map.ExpressionMap;
import com.yehebl.orm.data.mysql.MySqlExpressionManager.Expression;
import com.yehebl.orm.dto.ClassInfo;
import com.yehebl.orm.dto.FieldInfo;
import com.yehebl.orm.enums.IdType;
import com.yehebl.orm.manager.MethodAccessManager;
import com.yehebl.orm.util.SqlLogUtil;
import org.springframework.jdbc.support.GeneratedKeyHolder;

import java.sql.SQLException;
import java.util.*;
import java.util.Map.Entry;

/**
 * db操作实现类
 *
 * @author tzd
 */
public class MySqlDao extends CommonDao implements IDao {

    public MySqlDao(IConfig config) {
        super(config);
    }

    @Override
    public int save(Object entity) {
        ClassInfo ci = getClassInfo(entity.getClass());
        List<FieldInfo> list = ci.getIdFieldInfo();
        FieldInfo returnKey = null;
        for (FieldInfo fi : list) {
            if (fi.getIdType().equals(IdType.auto)) {
                Object o1 = MethodAccessManager.get(ci.getClazz()).invoke(entity, ("get" + fi.getUpperFieldName()));
                if (o1 != null) {
                    fi.setObject(o1);
                    continue;
                }
            }
            Object o = config.getAutoId(fi.getIdType());
            if (fi.getIdType().equals(IdType.generated)) {
                returnKey = fi;
            }
            if (o == null) {
                continue;
            }

            fi.setObject(o);
            MethodAccessManager.get(ci.getClazz()).invoke(entity, ("set" + fi.getUpperFieldName()), o);
        }
        String sql = MySqlSqlManager.getInsert(ci);
        Object[] objs = new Object[ci.getTableFieldMap().size()];
        int index = 0;
        for (FieldInfo fi : ci.getTableFieldMap().values()) {
            Object o = fi.getIdType() != null ? fi.getObject()
                    : MethodAccessManager.get(ci.getClazz()).invoke(entity, ("get" + fi.getUpperFieldName()));
            objs[index++] = o;
        }
        SqlLogUtil.print(config, sql, objs);
        try {
            if (returnKey == null) {
                return config.getJdbc().update(sql, objs);
            }
            GeneratedKeyHolder gk = new GeneratedKeyHolder();
            int result = config.getJdbc().insert(sql, gk, objs);
            Object key = gk.getKeyList().get(0).get("GENERATED_KEY");
            MethodAccessManager.get(ci.getClazz()).invoke(entity, ("set" + returnKey.getUpperFieldName()),
                    ResultSetManager.convert(returnKey.getFieldType(), key));
            return result;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int save(Map<String, Object> map, String tableName) {
        StringBuilder sb = new StringBuilder();
        sb.append("insert into `").append(tableName).append("`(");
        StringBuilder paramsSb = new StringBuilder();
        Object[] objs = new Object[map.size()];
        int i = 0;
        for (Entry<String, Object> entry : map.entrySet()) {
            objs[i] = entry.getValue();
            i++;
            if (i >= objs.length) {
                paramsSb.append("?");
                sb.append("`").append(entry.getKey()).append("`)");
            } else {
                paramsSb.append("?,");
                sb.append("`").append(entry.getKey()).append("`,");
            }
        }
        String sql = sb + "values(" + paramsSb + ")";
        SqlLogUtil.print(config, sql, objs);
        try {
            return config.getJdbc().update(sql, objs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int[] save(Collection<Map<String, Object>> maps, String tableName) {
        int[] result = new int[maps.size()];
        int i = 0;
        for (Map<String, Object> map : maps) {
            result[i] = save(map, tableName);
            i++;
        }
        return result;
    }

    @Override
    public <T> int[] save(Collection<T> entitys) {
        if (entitys == null || entitys.size() == 0) {
            return new int[]{0};
        }
        ClassInfo ci = getClassInfo(entitys);
        List<FieldInfo> list = ci.getIdFieldInfo();
        for (FieldInfo fi : list) {
            for (T c : entitys) {
                if (fi.getIdType().equals(IdType.auto)) {
                    Object o1 = MethodAccessManager.get(ci.getClazz()).invoke(c, ("get" + fi.getUpperFieldName()));
                    if (o1 != null) {
                        continue;
                    }
                }
                Object o = config.getAutoId(fi.getIdType());
                if (o == null) {
                    continue;
                }
                MethodAccessManager.get(ci.getClazz()).invoke(c, ("set" + fi.getUpperFieldName()), o);
            }

        }
        String sql = MySqlSqlManager.getInsert(ci);
        Object[][] objs = new Object[entitys.size()][];
        int index = 0;

        for (T t : entitys) {
            Object[] objs1 = new Object[ci.getTableFieldMap().size()];
            int index1 = 0;
            for (FieldInfo fi : ci.getTableFieldMap().values()) {
                Object o = MethodAccessManager.get(ci.getClazz()).invoke(t, ("get" + fi.getUpperFieldName()));
                objs1[index1] = o;
                index1++;
            }

            SqlLogUtil.print(config, sql, objs1);
            objs[index] = objs1;
            index++;
        }
        try {
            return config.getJdbc().batchUpdate(sql, objs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> int update(T entity, ICopyProperties<T> copyProperties, final Class<T> clazz) {
        final ClassInfo ci = getClassInfo(entity.getClass());
        String sql = MySqlSqlManager.getSelect(ci);
        String resultSql = sql + MySqlSqlManager.getIdWhere(ci);
        final Object[] objs = new Object[ci.getIdFieldInfo().size()];
        for (int i = 0; i < ci.getIdFieldInfo().size(); i++) {
            FieldInfo fi = ci.getIdFieldInfo().get(i);
            Object o = MethodAccessManager.get(ci.getClazz()).invoke(entity, ("get" + fi.getUpperFieldName()));
            objs[i] = o;
        }
        SqlLogUtil.print(config, resultSql, objs);
        try {
            T rsEntity = config.getJdbc().query(resultSql, rs -> ResultSetManager.toRsEntity(rs, ci, clazz), objs);
            if (rsEntity == null) {
                throw new RuntimeException("更新实体不能为null");
            }
            copyProperties.copy(entity, rsEntity);
            return update(rsEntity);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int update(Object entity) {
        ClassInfo ci = getClassInfo(entity.getClass());
        String sql = MySqlSqlManager.getUpdate(ci);
        Object[] objs = new Object[ci.getTableFieldMap().size() + ci.getIdFieldInfo().size()];
        StringBuilder whereIds = new StringBuilder();
        int index = 0;
        int whereIndex = ci.getTableFieldMap().size();
        for (FieldInfo fi : ci.getTableFieldMap().values()) {
            Object o = MethodAccessManager.get(ci.getClazz()).invoke(entity, ("get" + fi.getUpperFieldName()));
            if (fi.getIdType() != null) {
                if (whereIds.length() == 0) {
                    whereIds.append(" where `").append(fi.getTableFieldName()).append("`=? ");
                } else {
                    whereIds.append("and `").append(fi.getTableFieldName()).append("`=?");
                }
                objs[whereIndex] = o;
                whereIndex++;
            }
            objs[index] = o;
            index++;
        }
        String resultSql = sql + whereIds;
        SqlLogUtil.print(config, resultSql, objs);
        try {
            return config.getJdbc().update(resultSql, objs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int update(String sql, Class<?> clazz, final Object... obj) {
        try {
            SqlLogUtil.print(config, sql, obj);
            return config.getJdbc().update(sql, obj);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int update(String sql, final Object... obj) {
        try {
            SqlLogUtil.print(config, sql, obj);
            return config.getJdbc().update(sql, obj);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public int updateFilterNull(Object entity) {
        ClassInfo ci = getClassInfo(entity.getClass());
        StringBuilder sb = new StringBuilder();
        sb.append("update `").append(ci.getTableName()).append("` set ");
        List<Object> objectList = new ArrayList<>(ci.getTableFieldMap().size() + ci.getIdFieldInfo().size());
        for (FieldInfo fi : ci.getTableFieldMap().values()) {
            Object o = MethodAccessManager.get(ci.getClazz()).invoke(entity, ("get" + fi.getUpperFieldName()));
            if (o == null) {
                continue;
            }
            sb.append("`").append(fi.getTableFieldName()).append("`=?,");
            objectList.add(o);
        }
        sb.delete(sb.length() - 1, sb.length());
        StringBuilder whereIds = new StringBuilder();
        for (FieldInfo fi : ci.getTableFieldMap().values()) {
            if (fi.getIdType() != null) {
                Object o = MethodAccessManager.get(ci.getClazz()).invoke(entity, ("get" + fi.getUpperFieldName()));
                if (whereIds.length() == 0) {
                    whereIds.append(" where `").append(fi.getTableFieldName()).append("`=? ");
                } else {
                    whereIds.append("and `").append(fi.getTableFieldName()).append("`=?");
                }
                objectList.add(o);
            }

        }
        String resultSql = sb.toString() + whereIds;
        Object[] objs = listToArray(objectList);
        SqlLogUtil.print(config, resultSql, objs);
        try {
            return config.getJdbc().update(resultSql, objs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int updateByMap(Object entity, Map<String, Object> params, Set<String> acceptSet) {
        final ClassInfo ci = getClassInfo(entity.getClass());
        try {
            int index = 0;
            Object[] objs;
            if (acceptSet == null || acceptSet.size() == 0) {
                objs = new Object[ci.getTableFieldMap().size()];
            } else {
                objs = new Object[acceptSet.size()];
            }
            ExpressResult exResult = MySqlExpressionManager.getUpdateSql(ci, params, acceptSet);

            for (FieldInfo fi : ci.getTableFieldMap().values()) {
                if (acceptSet != null && !acceptSet.contains(fi.getFieldName())) {
                    continue;
                }
                Object o = MethodAccessManager.get(ci.getClazz()).invoke(entity, ("get" + fi.getUpperFieldName()));
                objs[index++] = o;
            }
            Object[] finalObjs = new Object[exResult.getObjs().length + objs.length];
            int finalInDex = 0;
            for (Object obj : objs) {
                finalObjs[finalInDex++] = obj;
            }
            for (int i = 0; i < exResult.getObjs().length; i++) {
                finalObjs[finalInDex++] = exResult.getObjs()[i];
            }
            SqlLogUtil.print(config, exResult.getSql(), finalObjs);
            return config.getJdbc().update(exResult.getSql(), finalObjs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int updateFilterByMap(Object entity, Map<String, Object> params, Set<String> filterSet) {
        final ClassInfo ci = getClassInfo(entity.getClass());
        try {
            int index = 0;
            Object[] objs;
            if (filterSet == null) {
                objs = new Object[ci.getTableFieldMap().size()];
            } else {
                objs = new Object[ci.getTableFieldMap().size() - filterSet.size()];
            }
            ExpressResult exResult = MySqlExpressionManager.getUpdateFilterSql(ci, params, filterSet);

            for (FieldInfo fi : ci.getTableFieldMap().values()) {
                if (filterSet != null && filterSet.contains(fi.getFieldName())) {
                    continue;
                }
                Object o = MethodAccessManager.get(ci.getClazz()).invoke(entity, ("get" + fi.getUpperFieldName()));
                objs[index++] = o;
            }
            Object[] finalObjs = new Object[exResult.getObjs().length + objs.length];
            int finalInDex = 0;
            for (Object obj : objs) {
                finalObjs[finalInDex++] = obj;
            }
            for (int i = 0; i < exResult.getObjs().length; i++) {
                finalObjs[finalInDex++] = exResult.getObjs()[i];
            }
            SqlLogUtil.print(config, exResult.getSql(), finalObjs);
            return config.getJdbc().update(exResult.getSql(), finalObjs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int updateByMap(Object entity, Map<String, Object> params, String... updateField) {
        Set<String> acceptSet = new HashSet<>();
        Collections.addAll(acceptSet, updateField);
        return updateByMap(entity, params, acceptSet);
    }

    @Override
    public int updateFilterByMap(Object entity, Map<String, Object> params, String... filterField) {
        Set<String> filterSet = new HashSet<>();
        Collections.addAll(filterSet, filterField);
        return updateFilterByMap(entity, params, filterSet);
    }

    @Override
    public int update(Object entity, String... updateField) {
        Set<String> acceptMap = new HashSet<>();
        Collections.addAll(acceptMap, updateField);
        ClassInfo ci = getClassInfo(entity.getClass());
        String sql = MySqlSqlManager.getUpdate(ci, acceptMap);
        Object[] objs = new Object[acceptMap.size() + ci.getIdFieldInfo().size()];
        StringBuilder whereIds = new StringBuilder();
        int index = 0;
        int whereIndex = acceptMap.size();
        for (FieldInfo fi : ci.getTableFieldMap().values()) {
            Object o = MethodAccessManager.get(ci.getClazz()).invoke(entity, ("get" + fi.getUpperFieldName()));
            if (fi.getIdType() != null) {
                if (whereIds.length() == 0) {
                    whereIds.append(" where `").append(fi.getTableFieldName()).append("`=? ");
                } else {
                    whereIds.append("and `").append(fi.getTableFieldName()).append("`=?");
                }
                objs[whereIndex++] = o;
            }
            if (!acceptMap.contains(fi.getFieldName())) {
                continue;
            }
            objs[index++] = o;
        }
        String resultSql = sql + whereIds;
        SqlLogUtil.print(config, resultSql, objs);
        try {
            return config.getJdbc().update(resultSql, objs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int updateFilter(Object entity, String... filterField) {
        Set<String> filterSet = new HashSet<>();
        int filterFieldLength = 0;
        if (filterField != null) {
            Collections.addAll(filterSet, filterField);
            filterFieldLength = filterField.length;
        }
        ClassInfo ci = getClassInfo(entity.getClass());
        String sql = MySqlSqlManager.getUpdateFilter(ci, filterSet);
        Object[] objs = new Object[ci.getTableFieldMap().size() - filterFieldLength + ci.getIdFieldInfo().size()];
        StringBuilder whereIds = new StringBuilder();
        int index = 0;
        int whereIndex = ci.getTableFieldMap().size() - filterFieldLength;
        for (FieldInfo fi : ci.getTableFieldMap().values()) {
            Object o = MethodAccessManager.get(ci.getClazz()).invoke(entity, ("get" + fi.getUpperFieldName()));
            if (fi.getIdType() != null) {
                if (whereIds.length() == 0) {
                    whereIds.append(" where `").append(fi.getTableFieldName()).append("`=? ");
                } else {
                    whereIds.append("and `").append(fi.getTableFieldName()).append("`=?");
                }
                objs[whereIndex++] = o;
            }
            if (filterSet.contains(fi.getFieldName())) {
                continue;
            }
            objs[index++] = o;
        }
        String resultSql = sql + whereIds;
        SqlLogUtil.print(config, resultSql, objs);
        try {
            return config.getJdbc().update(resultSql, objs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> int[] update(Collection<T> entitys) {
        if (entitys == null || entitys.size() == 0) {
            return new int[]{0};
        }
        ClassInfo ci = getClassInfo(entitys);
        String sql = MySqlSqlManager.getUpdate(ci);
        final Object[][] objs = new Object[entitys.size()][];
        StringBuilder whereIds = new StringBuilder();
        String resultSql = null;
        int objsIndex = 0;
        boolean flag = true;
        for (T t : entitys) {
            Object[] parameters1 = new Object[ci.getTableFieldMap().size() + ci.getIdFieldInfo().size()];
            int index = 0;
            int whereIndex = ci.getTableFieldMap().size();
            for (FieldInfo fi : ci.getTableFieldMap().values()) {
                Object o = MethodAccessManager.get(ci.getClazz()).invoke(t, ("get" + fi.getUpperFieldName()));
                if (fi.getIdType() != null) {
                    if (flag) {
                        if (whereIds.length() == 0) {
                            whereIds.append(" where `").append(fi.getTableFieldName()).append("`=? ");
                        } else {
                            whereIds.append("and `").append(fi.getTableFieldName()).append("`=?");
                        }
                        resultSql = sql + whereIds;
                    }
                    parameters1[whereIndex++] = o;
                }
                parameters1[index++] = o;
            }
            flag = false;
            objs[objsIndex++] = parameters1;
            SqlLogUtil.print(config, resultSql, parameters1);
        }
        try {
            return config.getJdbc().batchUpdate(resultSql, objs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int delete(Object entity) {
        if (entity == null) {
            return 0;
        }
        ClassInfo ci = getClassInfo(entity.getClass());
        String sql = MySqlSqlManager.getDelete(ci);
        final Object[] obj = new Object[ci.getIdFieldInfo().size()];
        int index = 0;
        for (FieldInfo fi : ci.getIdFieldInfo()) {
            Object o = MethodAccessManager.get(ci.getClazz()).invoke(entity, ("get" + fi.getUpperFieldName()));
            obj[index++] = o;
        }
        String resultSql = sql + MySqlSqlManager.getIdWhere(ci);
        try {
            SqlLogUtil.print(config, resultSql, obj);
            return config.getJdbc().update(resultSql, obj);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> int[] delete(Collection<T> entitys) {
        if (entitys == null || entitys.size() == 0) {
            return new int[]{0};
        }
        ClassInfo ci = getClassInfo(entitys);
        String sql = MySqlSqlManager.getDelete(ci) + MySqlSqlManager.getIdWhere(ci);
        Object[][] objs = new Object[entitys.size()][ci.getIdFieldInfo().size()];
        int i = 0;
        for (T t : entitys) {
            int index = 0;
            Object[] objs1 = new Object[ci.getIdFieldInfo().size()];
            for (FieldInfo fi : ci.getIdFieldInfo()) {
                Object o = MethodAccessManager.get(ci.getClazz()).invoke(t, ("get" + fi.getUpperFieldName()));
                objs1[index] = o;
                index++;
            }
            objs[i] = objs1;
            i++;
            SqlLogUtil.print(config, sql, objs1);
        }
        try {
            return config.getJdbc().batchUpdate(sql, objs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> int deleteIn(String ids, Class<T> clazz) {
        String[] idArray = ids.split(",");
        ClassInfo ci = getClassInfo(clazz);
        String sql = MySqlSqlManager.getDelete(ci);
        StringBuilder whereIds = new StringBuilder();
        final Object[] objs = new Object[idArray.length];
        for (int i = 0; i < idArray.length; i++) {
            objs[i] = idArray[i];
            whereIds.append("?,");
        }
        if (whereIds.length() > 0) {
            whereIds.delete(whereIds.length() - 1, whereIds.length());
        }
        String resultSql = sql + " where  `" + ci.getIdFieldInfo().get(0).getTableFieldName() + "` in ("
                + whereIds + ")";
        try {
            SqlLogUtil.print(config, resultSql, objs);
            return config.getJdbc().update(resultSql, objs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> int deleteById(Object id, Class<T> clazz) {
        ClassInfo ci = getClassInfo(clazz);
        String sql = MySqlSqlManager.getDelete(ci);
        String resultSql = sql + MySqlSqlManager.getIdWhere(ci);
        final Object[] objs = new Object[ci.getIdFieldInfo().size()];
        if (ci.getIdFieldInfo().size() == 1) {
            objs[0] = id;
        } else {
            for (int i = 0; i < ci.getIdFieldInfo().size(); i++) {
                FieldInfo fi = ci.getIdFieldInfo().get(i);
                Object o = MethodAccessManager.get(ci.getClazz()).invoke(id, ("get" + fi.getUpperFieldName()));
                objs[i] = o;
            }
        }
        try {
            SqlLogUtil.print(config, resultSql, objs);
            return config.getJdbc().update(resultSql, objs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> int deleteByExpression(String expression, String value, Class<T> clazz) {
        ClassInfo ci = getClassInfo(clazz);
        try {
            ExpressResult exResult = MySqlExpressionManager.getDeleteSql(expression, ci, value);
            if (exResult.getObjs() != null) {
                SqlLogUtil.print(config, exResult.getSql(), exResult.getObj());
                return config.getJdbc().update(exResult.getSql(), exResult.getObjs());
            }
            SqlLogUtil.print(config, exResult.getSql(), exResult.getObj());
            return config.getJdbc().update(exResult.getSql(), exResult.getObj());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> int deleteByMap(Map<String, Object> params, Class<T> clazz) {
        final ClassInfo ci = getClassInfo(clazz);
        try {
            ExpressResult exResult = MySqlExpressionManager.getDeleteSql(ci, params);
            SqlLogUtil.print(config, exResult.getSql(), exResult.getObjs());
            return config.getJdbc().update(exResult.getSql(), exResult.getObjs());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> T get(Object id, final Class<T> clazz) {
        T t;
        final ClassInfo ci = getClassInfo(clazz);
        String sql = MySqlSqlManager.getSelect(ci);
        String resultSql = sql + MySqlSqlManager.getIdWhere(ci);
        final Object[] objs = new Object[ci.getIdFieldInfo().size()];
        if (ci.getIdFieldInfo().size() == 1) {
            objs[0] = id;
        } else {
            for (int i = 0; i < ci.getIdFieldInfo().size(); i++) {
                FieldInfo fi = ci.getIdFieldInfo().get(i);
                Object o = MethodAccessManager.get(ci.getClazz()).invoke(id, ("get" + fi.getUpperFieldName()));
                objs[i] = o;
            }
        }
        SqlLogUtil.print(config, resultSql, objs);
        try {
            t = config.getJdbc().query(resultSql, rs -> ResultSetManager.toRsEntity(rs, ci, clazz), objs);
            return t;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> T getBySqlName(String sqlName, AQueryXmlSql queryXmlSql, final Class<T> clazz) {
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        if (xmlSql == null && queryXmlSql.getSql() == null) {
            throw new RuntimeException("xml里面没找到：" + sqlName);
        }
        final List<Object> list = new ArrayList<>();
        String sql = queryXmlSql.getResultSql(xmlSql, list).toString();
        Object[] objs = listToArray(list);
        final ClassInfo ci = getClassInfo(clazz);
        T t;
        try {
            SqlLogUtil.print(config, sql, objs);
            t = config.getJdbc().query(sql, rs -> ResultSetManager.toRsManyEntityBySqlName(rs, ci, clazz), objs);
            return t;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> T getOneBySqlName(String sqlName, AQueryXmlSql queryXmlSql, final Class<T> clazz) {
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        if (xmlSql == null && queryXmlSql.getSql() == null) {
            throw new RuntimeException("xml里面没找到：" + sqlName);
        }
        final List<Object> list = new ArrayList<>();
        String sql = queryXmlSql.getResultSql(xmlSql, list).toString() + " limit 1";
        Object[] objs = listToArray(list);
        final ClassInfo ci = getClassInfo(clazz);
        try {
            SqlLogUtil.print(config, sql, objs);
            return config.getJdbc().query(sql, rs -> ResultSetManager.toRsManyEntityBySqlName(rs, ci, clazz), objs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> List<T> findBySqlName(String sqlName, AQueryXmlSql queryXmlSql, final Class<T> clazz) {
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        if (xmlSql == null) {
            throw new RuntimeException("xml没找到：" + sqlName);
        }
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        final List<Object> list = new ArrayList<>();
        String sql = queryXmlSql.getResultSql(xmlSql, list).toString();
        Object[] objs = listToArray(list);
        try {
            SqlLogUtil.print(config, sql, objs);
            return config.getJdbc().query(sql, rs -> ResultSetManager.toRsManyListBySqlName(rs, clazz), objs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> Page<T> findPageBySqlName(String sqlName, AQueryXmlSql queryXmlSql, int page, int size,
                                         final Class<T> clazz) {
        return findPageBySqlName(sqlName, queryXmlSql, page, size, null, clazz);
    }

    @Override
    public <T> Page<T> findPageBySqlName(String sqlName, AQueryXmlSql queryXmlSql, int page, int size, Integer pageType, Class<T> clazz) {
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        if (xmlSql == null && queryXmlSql.getSql() == null) {
            throw new RuntimeException("xml里面没找到：" + sqlName);
        }
        final List<Object> list = new ArrayList<>();
        StringBuilder sql = queryXmlSql.getResultSql(xmlSql, list);
        Object[] objs = listToArray(list);
        Object[] objs1 = objs;
        String getCountXml = null;
        if (isReturnPage(pageType)) {
            if (xmlSql != null && xmlSql.getAttributesMap().containsKey("countName")) {
                XmlSql xmlSql1 = XmlSqlManager.getSqlByName(xmlSql.getAttributesMap().get("countName"));
                if (xmlSql1 == null) {
                    throw new RuntimeException("xml里面没找到：" + xmlSql.getAttributesMap().get("countName"));
                }
                final List<Object> list1 = new ArrayList<>();
                getCountXml = queryXmlSql.getResultSql(xmlSql1, list1).toString();
                objs1 = listToArray(list1);
            } else {
                getCountXml = "select count(*) from (" + sql.toString() + ") table1";
            }
        }
        try {
            Page<T> page1 = new Page<>();
            if (isReturnPage(pageType)) {
                SqlLogUtil.print(config, getCountXml, objs1);
                int pageCount = config.getJdbc().query(getCountXml, ResultSetManager::getInt, objs1);
                page1.setPage(page);
                page1.setSize(size);
                page1.setRecords(pageCount);
            }
            if (isReturnPageData(pageType)) {
                if (page1.getRecords() != null && page1.getRecords() == 0) {
                    page1.setRows(new ArrayList<>(0));
                    return page1;
                }
                sql.append(" limit ").append((page - 1) * size).append(",").append(size);
                SqlLogUtil.print(config, sql.toString(), objs);
                List<T> resultList = config.getJdbc().query(sql.toString(), rs -> ResultSetManager.toRsManyListBySqlName(rs, clazz), objs);
                page1.setRows(resultList);
            }
            return page1;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private boolean isReturnPageData(Integer pageType) {
        return (pageType == null || pageType == 1 || pageType == 2);
    }

    private boolean isReturnPage(Integer pageType) {
        return (pageType == null || pageType == 1 || pageType == 3);
    }

    @Override
    public <T> List<T> findBySqlName(String sqlName, AQueryXmlSql queryXmlSql, int size, final Class<T> clazz) {
        return findBySqlName(sqlName, queryXmlSql, null, size, clazz);
    }

    @Override
    public Object getObjectBySqlName(String sqlName, AQueryXmlSql queryXmlSql) {
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        if (xmlSql == null && queryXmlSql.getSql() == null) {
            throw new RuntimeException("xml里面没找到：" + sqlName);
        }
        final List<Object> list = new ArrayList<>();
        StringBuilder sql = queryXmlSql.getResultSql(xmlSql, list);
        Object[] objs = listToArray(list);
        try {
            SqlLogUtil.print(config, sql.toString(), objs);
            return config.getJdbc().query(sql.toString(), ResultSetManager::getObj, objs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public ResultObject getResultObjectBySqlName(String sqlName, AQueryXmlSql queryXmlSql) {
        ResultObject ro = new ResultObject();
        ro.setObj(getObjectBySqlName(sqlName, queryXmlSql));
        return ro;
    }

    @Override
    public ResultObject getResultObjectBySqlName(String sqlName) {
        ResultObject ro = new ResultObject();
        ro.setObj(getObjectBySqlName(sqlName));
        return ro;
    }

    @Override
    public <T> T getBySqlName(String sqlName, Class<T> clazz) {
        return getBySqlName(sqlName, null, clazz);
    }

    @Override
    public <T> T getOneBySqlName(String sqlName, Class<T> clazz) {
        return getOneBySqlName(sqlName, null, clazz);
    }

    @Override
    public <T> List<T> findBySqlName(String sqlName, Class<T> clazz) {
        return findBySqlName(sqlName, null, clazz);
    }

    @Override
    public <T> Page<T> findPageBySqlName(String sqlName, int page, int size, Class<T> clazz) {
        return findPageBySqlName(sqlName, null, page, size, clazz);
    }

    @Override
    public <T> Page<T> findPageBySqlName(String sqlName, int page, int size, Integer pageType, Class<T> clazz) {
        return findPageBySqlName(sqlName, null, page, size, pageType, clazz);
    }

    @Override
    public <T> List<T> findBySqlName(String sqlName, int size, Class<T> clazz) {
        return findBySqlName(sqlName, null, size, clazz);
    }

    @Override
    public Object getObjectBySqlName(String sqlName) {
        return getObjectBySqlName(sqlName, new QueryXmlSql());
    }

    @Override
    public <T> List<T> findAll(final Class<T> clazz) {
        final ClassInfo ci = getClassInfo(clazz);
        String sql = MySqlSqlManager.getSelect(ci);
        try {
            SqlLogUtil.print(config, sql);
            return config.getJdbc().query(sql, rs -> ResultSetManager.toRsList(rs, ci, clazz));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> List<T> findByExpression(String expression, Object value, final Class<T> clazz) {
        final ClassInfo ci = getClassInfo(clazz);
        try {
            ExpressResult exResult = MySqlExpressionManager.getSelectSql(ci, expression, value);
            if (exResult.getObjs() != null) {
                SqlLogUtil.print(config, exResult.getSql(), exResult.getObjs());
                return config.getJdbc().query(exResult.getSql(), rs -> ResultSetManager.toRsList(rs, ci, clazz), exResult.getObjs());
            }
            SqlLogUtil.print(config, exResult.getSql(), exResult.getObj());
            if (exResult.getObj() == null) {
                return config.getJdbc().query(exResult.getSql(), rs -> ResultSetManager.toRsList(rs, ci, clazz));
            }
            return config.getJdbc().query(exResult.getSql(), rs -> ResultSetManager.toRsList(rs, ci, clazz), exResult.getObj());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> T getByExpression(String expression, Object value, final Class<T> clazz) {
        final ClassInfo ci = getClassInfo(clazz);
        try {
            ExpressResult exResult = MySqlExpressionManager.getSelectSql(ci, expression, value);
            if (exResult.getObjs() != null) {
                SqlLogUtil.print(config, exResult.getSql(), exResult.getObjs());
                return config.getJdbc().query(exResult.getSql(), rs -> ResultSetManager.toRsEntity(rs, ci, clazz), exResult.getObjs());
            }
            SqlLogUtil.print(config, exResult.getSql(), exResult.getObj());
            if (exResult.getObj() == null) {
                return config.getJdbc().query(exResult.getSql(), rs -> ResultSetManager.toRsEntity(rs, ci, clazz));
            }
            return config.getJdbc().query(exResult.getSql(), rs -> ResultSetManager.toRsEntity(rs, ci, clazz), exResult.getObj());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> T getByMap(Map<String, Object> params, final Class<T> clazz) {
        final ClassInfo ci = getClassInfo(clazz);
        try {
            ExpressResult exResult = MySqlExpressionManager.getSelectSql(ci, params);
            SqlLogUtil.print(config, exResult.getSql(), exResult.getObjs());
            return config.getJdbc().query(exResult.getSql(), rs -> ResultSetManager.toRsEntity(rs, ci, clazz), exResult.getObjs());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> List<T> findByMap(Map<String, Object> params, final Class<T> clazz) {
        final ClassInfo ci = getClassInfo(clazz);
        try {
            ExpressResult exResult = MySqlExpressionManager.getSelectSql(ci, params);
            SqlLogUtil.print(config, exResult.getSql(), exResult.getObjs());
            return config.getJdbc().query(exResult.getSql(), rs -> ResultSetManager.toRsList(rs, ci, clazz), exResult.getObjs());

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> List<T> findByMap(Map<String, Object> params, Integer page, Integer size, final Class<T> clazz) {
        final ClassInfo ci = getClassInfo(clazz);
        try {
            ExpressResult exResult = MySqlExpressionManager.getSelectSql(ci, params);
            String result;
            if (page != null && size != null) {
                result = exResult.getSql() + " limit " + ((page - 1) * size) + "," + size;
            } else if (size != null) {
                result = exResult.getSql() + " limit " + size;
            } else {
                result = exResult.getSql();
            }
            SqlLogUtil.print(config, result, exResult.getObjs());
            return config.getJdbc().query(result, rs -> ResultSetManager.toRsList(rs, ci, clazz), exResult.getObjs());

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> List<T> findByMap(Map<String, Object> params, Integer size, final Class<T> clazz) {
        return findByMap(params, null, size, clazz);
    }

    @Override
    public <T> Page<T> findPageBySql(String sql, int page, int size, final Class<T> clazz, final Object... objs) {
        return findPageBySql(sql, page, size, null, clazz, objs);
    }

    @Override
    public <T> Page<T> findPageBySql(String sql, int page, int size, Integer pageType, Class<T> clazz, Object... objs) {
        Page<T> page1 = new Page<>();
        page1.setPage(page);
        page1.setSize(size);
        try {
            if (isReturnPage(pageType)) {
                StringBuilder sb = new StringBuilder();
                sb.append("select count(*) from (");
                sb.append(sql).append(")  countTable");
                SqlLogUtil.print(config, sb.toString(), objs);
                int pageCount = config.getJdbc().query(sb.toString(), ResultSetManager::getInt, objs);
                page1.setRecords(pageCount);
            }
            if (isReturnPageData(pageType)) {
                if (page1.getRecords() != null && page1.getRecords() == 0) {
                    page1.setRows(new ArrayList<>(0));
                    return page1;
                }
                String findSql = sql + " limit " + ((page - 1) * size) + "," + size;
                SqlLogUtil.print(config, findSql, objs);
                List<T> list = config.getJdbc().query(findSql, rs -> ResultSetManager.toRsManyListBySqlName(rs, clazz), objs);
                page1.setRows(list);
            }
            return page1;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> Page<T> findPageByMap(int page, int size, Map<String, Object> params, final Class<T> clazz) {
        return findPageByMap(page, size, null, params, clazz);
    }

    @Override
    public <T> Page<T> findPageByMap(int page, int size, Integer pageType, Map<String, Object> params, Class<T> clazz) {
        final ClassInfo ci = getClassInfo(clazz);
        Page<T> page1 = new Page<>();
        Integer pageMap = (Integer) params.get(Expression.PAGE.toString());
        Integer sizeMap = (Integer) params.get(Expression.SIZE.toString());
        page = pageMap == null ? page : pageMap;
        size = sizeMap == null ? size : sizeMap;
        page1.setPage(page);
        page1.setSize(size);
        try {
            ExpressResult exResult = MySqlExpressionManager.getSelectPageSql(ci, params);
            if (isReturnPage(pageType)) {
                SqlLogUtil.print(config, exResult.getCountSql(), exResult.getObjs());
                int pageCount = config.getJdbc().query(exResult.getCountSql(), ResultSetManager::getInt, exResult.getObjs());
                page1.setRecords(pageCount);
            }
            if (isReturnPageData(pageType)) {
                if (page1.getRecords() != null && page1.getRecords() == 0) {
                    page1.setRows(new ArrayList<>(0));
                    return page1;
                }
                String findSql = exResult.getSql() + " limit " + ((page - 1) * size) + "," + size;
                SqlLogUtil.print(config, findSql, exResult.getObjs());
                List<T> list1 = config.getJdbc().query(findSql, rs -> ResultSetManager.toRsList(rs, ci, clazz), exResult.getObjs());
                page1.setRows(list1);
            }
            return page1;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> List<T> findBySql(String sql, final Class<T> clazz, final Object... objs) {
        getClassInfo(clazz);
        try {
            SqlLogUtil.print(config, sql, objs);
            return config.getJdbc().query(sql, rs -> ResultSetManager.toRsManyListBySqlName(rs, clazz), objs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> Integer getCountByExpression(String expression, Object value, Class<T> clazz) {
        ClassInfo ci = getClassInfo(clazz);
        try {
            ExpressResult exResult = MySqlExpressionManager.getSelectCount(expression, ci, value);
            if (exResult.getObjs() != null) {
                SqlLogUtil.print(config, exResult.getSql(), exResult.getObjs());
                return config.getJdbc().query(exResult.getSql(), ResultSetManager::getInt, exResult.getObjs());
            }
            SqlLogUtil.print(config, exResult.getSql(), exResult.getObj());
            if (exResult.getObj() == null) {
                return config.getJdbc().query(exResult.getSql(), ResultSetManager::getInt);
            }
            return config.getJdbc().query(exResult.getSql(), ResultSetManager::getInt, exResult.getObj());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> Integer getCountByMap(Map<String, Object> params, Class<T> clazz) {
        ClassInfo ci = getClassInfo(clazz);
        try {
            ExpressResult exResult = MySqlExpressionManager.getSelectCount(ci, params);
            SqlLogUtil.print(config, exResult.getSql(), exResult.getObjs());
            return config.getJdbc().query(exResult.getSql(), ResultSetManager::getInt, exResult.getObjs());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> boolean isExists(String field, Object value, Class<T> clazz) {
        return isExists(null, field, value, clazz);
    }

    @Override
    public <T> boolean isExists(Object id, String field, Object value, Class<T> clazz) {
        if (id == null) {
            Integer count = getCountByExpression("EQ_" + field, value, clazz);
            return count > 0;
        } else {
            ClassInfo ci = getClassInfo(clazz);
            String sql = "select count(*) from `" + ci.getTableName() + "`";
            StringBuilder whereIds = new StringBuilder();
            for (FieldInfo fi : ci.getIdFieldInfo()) {
                if (whereIds.length() == 0) {
                    whereIds.append(" where `").append(fi.getTableFieldName()).append("`<> ?");
                } else {
                    whereIds.append(" and `").append(fi.getTableFieldName()).append("`<> ?");
                }
            }

            final Object[] objs = new Object[ci.getIdFieldInfo().size() + 1];
            if (ci.getIdFieldInfo().size() == 1) {
                objs[0] = id;
            } else {
                for (int i = 0; i < ci.getIdFieldInfo().size(); i++) {
                    FieldInfo fi = ci.getIdFieldInfo().get(i);
                    Object o = MethodAccessManager.get(ci.getClazz()).invoke(id, ("get" + fi.getUpperFieldName()));
                    objs[i] = o;
                }
            }
            FieldInfo fieldInfo = ci.getFieldMap().get(field);
            if (fieldInfo == null) {
                throw new RuntimeException(field + "字段不存在实体类" + clazz.getName() + "中");
            }
            whereIds.append(" and `").append(fieldInfo.getTableFieldName()).append("` = ?");
            objs[ci.getIdFieldInfo().size()] = value;
            String resultSql = sql + whereIds;
            SqlLogUtil.print(config, resultSql, objs);
            try {
                int count = config.getJdbc().query(resultSql, ResultSetManager::getInt, objs);
                return count > 0;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public <T> T getBySql(String sql, final Class<T> clazz, final Object... objs) {
        final ClassInfo ci = getClassInfo(clazz);
        try {
            SqlLogUtil.print(config, sql, objs);
            return config.getJdbc().query(sql, rs -> ResultSetManager.toRsManyEntityBySqlName(rs, ci, clazz), objs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Object getObjectBySql(String sql, final Object... objs) {
        try {
            SqlLogUtil.print(config, sql, objs);
            return config.getJdbc().query(sql, ResultSetManager::getObj, objs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static Object[] listToArray(List<Object> list) {
        Object[] objs = new Object[list.size()];
        for (int i = 0; i < list.size(); i++) {
            objs[i] = list.get(i);
        }
        return objs;
    }

    @Override
    public void execute(String sql) {
        try {
            SqlLogUtil.print(config, sql);
            config.getJdbc().execute(sql);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> Integer getCount(Class<T> clazz) {
        final ClassInfo ci = getClassInfo(clazz);

        String sql = "select count(*) from `" + ci.getTableName() + "`";
        try {
            SqlLogUtil.print(config, sql);
            return config.getJdbc().query(sql, ResultSetManager::getInt);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> T getOneByMap(Map<String, Object> params, final Class<T> clazz) {
        final ClassInfo ci = getClassInfo(clazz);
        try {
            ExpressResult exResult = MySqlExpressionManager.getSelectSql(ci, params);
            String resultSql = exResult.getSql() + " limit 1";
            SqlLogUtil.print(config, resultSql, exResult.getObjs());
            return config.getJdbc().query(resultSql, rs -> ResultSetManager.toRsEntity(rs, ci, clazz), exResult.getObjs());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 封装Map集合单表实体
     */
    @Override
    public Map<String, Object> getMapBySql(String sql, Object... objs) {
        try {
            SqlLogUtil.print(config, sql, objs);
            return config.getJdbc().query(sql, ResultSetManager::toMapEntity, objs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Map<String, Object> getMapBySqlName(String sqlName) {
        return getMapBySqlName(sqlName, null);
    }

    @Override
    public Map<String, Object> getMapBySqlName(String sqlName, AQueryXmlSql queryXmlSql) {
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        if (xmlSql == null) {
            throw new RuntimeException("xml里面没有找到：" + sqlName);
        }
        final List<Object> list = new ArrayList<>();
        String sql = queryXmlSql.getResultSql(xmlSql, list).toString();
        Object[] objects = listToArray(list);
        try {
            SqlLogUtil.print(config, sql, objects);
            return config.getJdbc().query(sql, ResultSetManager::toMapEntity, objects);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<Map<String, Object>> findMapBySqlName(String sqlName, AQueryXmlSql queryXmlSql, Integer size) {
        return findMapBySqlName(sqlName, queryXmlSql, null, size);
    }

    @Override
    public List<Map<String, Object>> findMapBySqlName(String sqlName, AQueryXmlSql queryXmlSql, Integer page,
                                                      Integer size) {
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        if (xmlSql == null) {
            throw new RuntimeException("xml没找到：" + sqlName);
        }
        final List<Object> list = new ArrayList<>();
        String sql = queryXmlSql.getResultSql(xmlSql, list).toString();
        if (page == null && size != null) {
            sql += " limit " + size;
        }
        if (page != null && size != null) {
            sql += " limit " + (page - 1) * size + "," + size;
        }
        Object[] objects = listToArray(list);
        try {
            SqlLogUtil.print(config, sql, objects);
            return config.getJdbc().query(sql, ResultSetManager::toMapListBySqlName, objects);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<Map<String, Object>> findMapBySqlName(String sqlName, AQueryXmlSql queryXmlSql) {
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        if (xmlSql == null) {
            throw new RuntimeException("xml没找到：" + sqlName);
        }
        final List<Object> list = new ArrayList<>();
        String sql = queryXmlSql.getResultSql(xmlSql, list).toString();
        Object[] objects = listToArray(list);
        try {
            SqlLogUtil.print(config, sql, objects);
            return config.getJdbc().query(sql, ResultSetManager::toMapListBySqlName, objects);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<Map<String, Object>> findMapBySqlName(String sqlName) {
        return findMapBySqlName(sqlName, null);
    }

    @Override
    public Page<Map<String, Object>> findMapPageBySql(String sql, int page, int size, Object... objs) {
        return findMapPageBySql(sql, null, page, size, objs);
    }

    @Override
    public Page<Map<String, Object>> findMapPageBySql(String sql, Integer pageType, int page, int size, Object... objs) {
        Page<Map<String, Object>> page1 = new Page<>();
        page1.setPage(page);
        page1.setSize(size);

        try {
            if (isReturnPage(pageType)) {
                StringBuilder sb = new StringBuilder();
                sb.append("select count(*) from (");
                sb.append(sql).append(")  countTable");
                SqlLogUtil.print(config, sb.toString(), objs);
                int pageCount = config.getJdbc().query(sb.toString(), ResultSetManager::getInt, objs);
                page1.setRecords(pageCount);
            }
            if (isReturnPageData(pageType)) {
                if (page1.getRecords() != null && page1.getRecords() == 0) {
                    page1.setRows(new ArrayList<>(0));
                    return page1;
                }
                String findSql = sql + " limit " + ((page - 1) * size) + "," + size;
                SqlLogUtil.print(config, findSql, objs);
                List<Map<String, Object>> list = config.getJdbc().query(findSql,
                        ResultSetManager::toRsMapList, objs);
                page1.setRows(list);
            }
            return page1;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Page<Map<String, Object>> findMapPageBySqlName(String sqlName, AQueryXmlSql queryXmlSql, int page,
                                                          int size) {
        return findMapPageBySqlName(sqlName, queryXmlSql, page, size, null);
    }

    @Override
    public Page<Map<String, Object>> findMapPageBySqlName(String sqlName, AQueryXmlSql queryXmlSql, int page, int size, Integer pageType) {
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        if (xmlSql == null && queryXmlSql.getSql() == null) {
            throw new RuntimeException("xml里面没找到：" + sqlName);
        }
        final List<Object> list = new ArrayList<>();
        StringBuilder sql = queryXmlSql.getResultSql(xmlSql, list);
        Object[] objs = listToArray(list);
        Object[] objs1 = objs;
        String getCountXml = null;
        if (isReturnPage(pageType)) {
            if (xmlSql != null && xmlSql.getAttributesMap().containsKey("countName")) {
                XmlSql xmlSql1 = XmlSqlManager.getSqlByName(xmlSql.getAttributesMap().get("countName"));
                if (xmlSql1 == null) {
                    throw new RuntimeException("xml里面没找到：" + xmlSql.getAttributesMap().get("countName"));
                }
                final List<Object> list1 = new ArrayList<>();
                getCountXml = queryXmlSql.getResultSql(xmlSql1, list1).toString();
                objs1 = listToArray(list1);
            } else {
                getCountXml = "select count(*) from (" + sql.toString() + ") table1";
            }
        }
        sql.append(" limit ").append((page - 1) * size).append(",").append(size);
        try {
            Page<Map<String, Object>> page1 = new Page<>();
            if (isReturnPage(pageType)) {
                SqlLogUtil.print(config, getCountXml, objs1);
                int pageCount = config.getJdbc().query(getCountXml, ResultSetManager::getInt, objs1);
                page1.setPage(page);
                page1.setSize(size);
                page1.setRecords(pageCount);
            }
            if (isReturnPageData(pageType)) {
                if (page1.getRecords() != null && page1.getRecords() == 0) {
                    page1.setRows(new ArrayList<>(0));
                    return page1;
                }
                SqlLogUtil.print(config, sql.toString(), objs);
                List<Map<String, Object>> resultList = config.getJdbc().query(sql.toString(),
                        ResultSetManager::toMapListBySqlName, objs);
                page1.setRows(resultList);
            }
            return page1;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Page<Map<String, Object>> findMapPageBySqlName(String sqlName, int page, int size) {
        return findMapPageBySqlName(sqlName, null, page, size);
    }

    @Override
    public Page<Map<String, Object>> findMapPageBySqlName(String sqlName, int page, int size, Integer pageType) {
        return findMapPageBySqlName(sqlName, null, page, size, null);
    }

    @Override
    public ResultObject getResultObjectBySql(String sql, Object... objs) {
        ResultObject ro = new ResultObject();
        ro.setObj(getObjectBySql(sql, objs));
        return ro;
    }

    @Override
    public ExpressionMap createExpressionMap() {
        return new ExpressionMap(this);
    }

    @Override
    public QueryXmlSql createQueryXmlSql(String sqlName) {
        return new QueryXmlSql(this, sqlName);
    }

    @Override
    public QueryXmlSql createQuerySql(String sql) {
        QueryXmlSql queryXmlSql = new QueryXmlSql(this);
        queryXmlSql.setSql(sql);
        return queryXmlSql;
    }

    @Override
    public <T> List<T> findBySqlName(String sqlName, AQueryXmlSql queryXmlSql, Integer page, Integer size,
                                     final Class<T> clazz) {
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        if (xmlSql == null && queryXmlSql.getSql() == null) {
            throw new RuntimeException("xml里面没找到：" + sqlName);
        }
        final List<Object> list = new ArrayList<>();
        StringBuilder sql = queryXmlSql.getResultSql(xmlSql, list);
        Object[] objs = listToArray(list);
        if (page == null && size != null) {
            sql.append(" limit ").append(size);
        } else if (page != null && size != null) {
            sql.append(" limit ").append((page - 1) * size).append(",").append(size);
        }
        try {
            SqlLogUtil.print(config, sql.toString(), objs);
            return config.getJdbc().query(sql.toString(), rs -> ResultSetManager.toRsManyListBySqlName(rs, clazz), objs);

        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public ISqlBuild createSqlBuild() {
        return new MySqlSqlBuild(this);
    }

    @Override
    public <T> SimplePage<T> findSimplePageBySqlName(String sqlName, AQueryXmlSql queryXmlSql, int page, int size,
                                                     Class<T> clazz) {
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        if (xmlSql == null && queryXmlSql.getSql() == null) {
            throw new RuntimeException("xml里面没找到：" + sqlName);
        }
        final List<Object> list = new ArrayList<>();
        StringBuilder sql = queryXmlSql.getResultSql(xmlSql, list);
        Object[] objs = listToArray(list);
        sql.append(" limit ").append((page - 1) * size).append(",").append(size);
        try {
            SqlLogUtil.print(config, sql.toString(), objs);
            return config.getJdbc().query(sql.toString(), rs -> ResultSetManager.toRsManyListBySqlName(rs, clazz, size), objs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> SimplePage<T> findSimplePageBySql(String sql, int page, int size, Class<T> clazz, Object... objs) {
        try {
            String findSql = sql + " limit " + ((page - 1) * size) + "," + (size);
            SqlLogUtil.print(config, findSql, objs);
            return config.getJdbc().query(findSql, rs -> ResultSetManager.toRsManyListBySqlName(rs, clazz, size), objs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> SimplePage<T> findSimplePageByMap(int page, int size, Map<String, Object> params, Class<T> clazz) {
        final ClassInfo ci = getClassInfo(clazz);
        Integer pageMap = (Integer) params.get(Expression.PAGE.toString());
        Integer sizeMap = (Integer) params.get(Expression.SIZE.toString());
        page = pageMap == null ? page : pageMap;
        size = sizeMap == null ? size : sizeMap;
        final int limitSize = size;
        try {
            ExpressResult exResult = MySqlExpressionManager.getSelectPageSql(ci, params);
            String findSql = exResult.getSql() + " limit " + ((page - 1) * size) + "," + (size);
            SqlLogUtil.print(config, findSql, exResult.getObjs());
            return config.getJdbc().query(findSql, rs -> ResultSetManager.toRsList(rs, ci, clazz, limitSize), exResult.getObjs());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public SimplePage<Map<String, Object>> findMapSimplePageBySql(String sql, int page, int size, Object... objs) {
        try {
            String findSql = sql + " limit " + ((page - 1) * size) + "," + (size);
            SqlLogUtil.print(config, findSql, objs);
            return config.getJdbc().query(findSql,
                    rs -> ResultSetManager.toRsMapList(rs, size), objs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public SimplePage<Map<String, Object>> findMapSimplePageBySqlName(String sqlName, AQueryXmlSql queryXmlSql,
                                                                      int page, int size) {
        queryXmlSql = queryXmlSql == null ? new QueryXmlSql() : queryXmlSql;
        XmlSql xmlSql = XmlSqlManager.getSqlByName(sqlName);
        if (xmlSql == null && queryXmlSql.getSql() == null) {
            throw new RuntimeException("xml里面没找到：" + sqlName);
        }
        final List<Object> list = new ArrayList<>();
        StringBuilder sql = queryXmlSql.getResultSql(xmlSql, list);
        Object[] objs = listToArray(list);
        sql.append(" limit ").append((page - 1) * size).append(",").append(size);
        try {
            SqlLogUtil.print(config, sql.toString(), objs);
            return config.getJdbc().query(sql.toString(),
                    rs -> ResultSetManager.toMapListBySqlName(rs, size), objs);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public SimplePage<Map<String, Object>> findMapSimplePageBySqlName(String sqlName, int page, int size) {
        return findMapSimplePageBySqlName(sqlName, null, page, size);
    }

    @Override
    public <T> SimplePage<T> findSimplePageBySqlName(String sqlName, int page, int size, Class<T> clazz) {
        return findSimplePageBySqlName(sqlName, null, page, size, clazz);
    }


}
